#ifndef YIGGRAPHICSSCENE_H
#define YIGGRAPHICSSCENE_H

// System includes
#include <QGraphicsScene>
#include <QTimer>
#include <QReadWriteLock>
#include <QThread>
#include <qgl.h>

// Local includes
#include "graphics/yigsynthgraphic.h"
//#include "graphics/yigglwidget.h"
#include "Server.h"
#include "SC_SndBuf.h"

/**
*   YigGraphicsScene
*   Exteneds QGraphicsScene adding graphics animation via opengl
*/
class YigGraphicsScene : public QGraphicsScene
{
    Q_OBJECT
public:

    /**
    *   YigGraphicsScene
    *   @param QObject *parent
    */
    explicit YigGraphicsScene(QObject *parent = 0);

    /**
    *   YigGraphicsScene deconstructor
    */
    ~YigGraphicsScene();

    /**
    *   setServerOptions sets the server options which we use to create new AudioBuffers with
    *   @param ServerOptions the instance of server options for the current scsynth server
    */
    void setServerOptions(sc::ServerOptions _options);

    /** addSynthBuffer adds a new SndBuf to the internal hash map and allows for synth animation buffer map updates
    *   @param int The audioOutBus index for the synth
    */
    void addSynthBuffer(int index);

    /** removeSynthBuffer removes a SndBuf from the internal hash map and allows for synth animation buffer map updates
    *   @param int The audioOutBus index for the synth
    */
    void removeSynthBuffer(int index);

    /** overridden to allow for opengl rendering of the background */
    void drawBackground(QPainter *painter, const QRectF &rect);

    /** overridden to allow for opengl rendering of the foreground */
    void drawForeground(QPainter *painter, const QRectF &rect);

    static const qreal PI;
    static const int AUDIO_ARROW_SIZE = 3;
    static const int MOD_ARROW_SIZE = 2;

signals:

    /**
    *   newSynthCollision Emitted when a new collision happens between synths
    *   @param YigSynthGraphic* synthGraphic Pointer to the new synth that was added to the collision data
    */
    //void newSynthCollision(YigSynthGraphic* synthGraphic);

    /**
    *   requestAudioBuffer is emitted when a new frame is requested and the snd buffers to be refilled
    *   @param QHash<int, SndBuf>* pointer to our internal buffer map
    */
    void requestAudioBuffers(QHash<int, SndBuf*>* buffers);

    /**
    *   requestAudioBuffer is emitted when a buffer needs to be filled
    *   @param int The index of the buffer to be filled
    *   @param SndBuf the actual memory buffer to be filled
    */
    void requestAudioBuffer(int index, SndBuf* buffer);

public slots:

private slots:

    void toggleGraphicsAnimation(bool animatingGraphics);
    /** called when a new audio buffer is requested from the buffer timer */
    void prepareBufferRequest();
    /** called when a new frame is requested from the fps timer */
    void drawForegroundFrame();
    /** called when a new background is requested from the backgroundFpsTimer */
    void drawBackgroundFrame();
    /** slot connected to collision timer,checks the collision item list and triggers auto cable based on the change in collisions*/
    //void checkNumberOfCollidingItems();

private:

    void createArrowDisplayLists();

    /** triggers background/foreground draw calls */
    QTimer foregroundFpsTimer, bufferTimer, backgroundFpsTimer;
    /** buffer frame to draw */
    int frame;
    /** the current index of the buffer that needs to be filled */
    int bufferToFill, bufferToFillKey;
    /** map of the current audio buffers to be drawn */
    QHash<int, SndBuf*>* currentBuffers;
    QReadWriteLock lock;
    /** server options to create new audio buffers with */
    sc::ServerOptions options;
    int radius;
    int diameter;
    /** thread where buffer access happens */
    QThread bufferThread;
    /** triggers collision checks at a regular interval */
    //QTimer collisionTimer;
    //int lastNumberOfCollidingItems;
    // Used for Arrow display lists
    GLuint audioArrowIndex;
    GLuint modArrowIndex;
    bool displayListsInitialized;
};

#endif // YIGGRAPHICSSCENE_H
